package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huiminpay.common.cache.Cache;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.RedisUtil;
import com.huiminpay.transaction.api.PayChannelService;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;

import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.util.List;

@Service
public class PayChannelServiceImpl implements PayChannelService {

  @Autowired
  private PlatformChannelMapper platformChannelMapper;

  @Autowired
  private AppPlatformChannelMapper appPlatformChannelMapper;

  @Resource
  private Cache cache;

  @Override
  public List<PlatformChannelDTO> queryPlatformChannel() {
    List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);
    List<PlatformChannelDTO> platformChannelDTOS = PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);
    return platformChannelDTOS;
  }
  @Override
  @Transactional
  public void bindPlatformChannelForApp(String appId, String platformChannelCodes) throws
          BusinessException {
    //根据appId和平台服务类型code查询app_platform_channel
    AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new
            LambdaQueryWrapper<AppPlatformChannel>()
            .eq(AppPlatformChannel::getAppId, appId)
            .eq(AppPlatformChannel::getPlatformChannel, platformChannelCodes));
    //如果没有绑定则绑定
    if(appPlatformChannel ==null){
      appPlatformChannel = new AppPlatformChannel();
      appPlatformChannel.setAppId(appId);
      appPlatformChannel.setPlatformChannel(platformChannelCodes);
      appPlatformChannelMapper.insert(appPlatformChannel);
    }
  }

  @Override
  public int queryAppBindPlatformChannel(String appId, String platformChannel) {
    int count = appPlatformChannelMapper.selectCount(
            new QueryWrapper<AppPlatformChannel>().lambda().eq(AppPlatformChannel::getAppId, appId)
                    .eq(AppPlatformChannel::getPlatformChannel, platformChannel));
    //已存在绑定关系返回1
    if (count > 0) {
      return 1;
    } else {
      return 0;
    }
  }


  @Override
  public List<PayChannelDTO> queryPayChannelByPlatformChannel(String platformChannelCode) {

    return platformChannelMapper.selectPayChannelByPlatformChannel(platformChannelCode);
  }

  @Autowired
  private PayChannelParamMapper payChannelParamMapper;


  /**
   \* 保存支付渠道参数
   \* @param payChannelParamDTO 支付渠道参数
   \* @throws BusinessException
   */
  @Override
  public void savePayChannelParam(PayChannelParamDTO payChannelParamDTO) throws BusinessException {
    if(payChannelParamDTO == null || StringUtils.isBlank(payChannelParamDTO.getAppId())
                                  || StringUtils.isBlank(payChannelParamDTO.getPlatformChannelCode())
                                  || StringUtils.isBlank(payChannelParamDTO.getPayChannel())){
      throw new BusinessException(CommonErrorCode.E_300009);
    }
    //根据appid和服务类型查询应用与服务类型绑定id
    Long appPlatformChannelId = selectIdByAppPlatformChannel(payChannelParamDTO.getAppId(), payChannelParamDTO.getPlatformChannelCode());
    if(appPlatformChannelId == null){
      //应用未绑定该服务类型不可进行支付渠道参数配置
      throw new BusinessException(CommonErrorCode.E_300010);
    }
    //根据应用与服务类型绑定id和支付渠道查询参数信息
    PayChannelParam payChannelParam = payChannelParamMapper.selectOne(new
            LambdaQueryWrapper<PayChannelParam>().eq(PayChannelParam::getAppPlatformChannelId,
            appPlatformChannelId)
            .eq(PayChannelParam::getPayChannel, payChannelParamDTO.getPayChannel()));
    //更新已有配置
    if (payChannelParam!=null){
      payChannelParam.setChannelName(payChannelParamDTO.getChannelName());
      payChannelParam.setParam(payChannelParamDTO.getParam());
      payChannelParamMapper.updateById(payChannelParam);
    }else{
      //添加新配置
      PayChannelParam entity =   PayChannelParamConvert.INSTANCE.dto2entity(payChannelParamDTO);
      entity.setId(null);
      //应用与服务类型绑定id
      entity.setAppPlatformChannelId(appPlatformChannelId);
      payChannelParamMapper.insert(entity);
    }
    //更新缓存
    updateCache(payChannelParamDTO.getAppId(),payChannelParamDTO.getPlatformChannelCode());
  }

  private void updateCache(String appId, String platformChannel) {
    //处理redis缓存
    //1.key的构建 如：SJ_PAY_PARAM:b910da455bc84514b324656e1088320b:huimin_c2b
    String redisKey = RedisUtil.keyBuilder(appId, platformChannel);
    //2.查询redis,检查key是否存在
    Boolean exists = cache.exists(redisKey);
    if (exists) {//存在，则清除
      //删除原有缓存
      cache.del(redisKey);
    }
    //3.从数据库查询应用的服务类型对应的实际支付参数，并重新存入缓存
    List<PayChannelParamDTO> paramDTOS = queryPayChannelParamByAppAndPlatform(appId,platformChannel);
    if (paramDTOS != null) {
      //存入缓存

      cache.set(redisKey, JSON.toJSON(paramDTOS).toString());
    }
  }

  /**
   * 根据应用和服务类型查询支付渠道参数列表
   *
   * @param appId           应用id
   * @param platformChannel 服务类型code
   * @return
   */
  @Override
  public List<PayChannelParamDTO> queryPayChannelParamByAppAndPlatform(String appId, String platformChannel) {
    //先从redis查询，如果有则返回
    //从缓存查询
    //1.key的构建 如：SJ_PAY_PARAM:b910da455bc84514b324656e1088320b:huimin_c2b
    String redisKey = RedisUtil.keyBuilder(appId, platformChannel);
    //是否有缓存
    Boolean exists = cache.exists(redisKey);
    if(exists){
      //从redis获取支付渠道参数列表（json串）
      String PayChannelParamDTO_String = cache.get(redisKey);
      //将json串转成 List<PayChannelParamDTO>
      List<PayChannelParamDTO> payChannelParamDTOS = JSON.parseArray(PayChannelParamDTO_String, PayChannelParamDTO.class);
      return payChannelParamDTOS;
    }

    //缓存中没有 则从数据库查询  根据应用和服务类型找到它们绑定id
    Long appPlatformChannelId = selectIdByAppPlatformChannel(appId, platformChannel);
    if(appPlatformChannelId == null){
      return null;
    }
    //应用和服务类型绑定id查询支付渠道参数记录
    List<PayChannelParam> payChannelParams = payChannelParamMapper.selectList(new LambdaQueryWrapper<PayChannelParam>().eq(PayChannelParam::getAppPlatformChannelId, appPlatformChannelId));
    List<PayChannelParamDTO> payChannelParamDTOS = PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParams);
    //存入缓存

    cache.set(redisKey, JSON.toJSON(payChannelParamDTOS).toString());

    return payChannelParamDTOS;
  }

  @Override
  public PayChannelParamDTO queryParamByAppPlatformAndPayChannel(String appId, String platformChannel, String payChannel) throws BusinessException {
    List<PayChannelParamDTO> payChannelParamDTOS = queryPayChannelParamByAppAndPlatform(appId, platformChannel);
    for(PayChannelParamDTO payChannelParam:payChannelParamDTOS){
      if(payChannelParam.getPayChannel().equals(payChannel)){
        return payChannelParam;
      }
    }
    return null;
  }

  /**
   * 根据应用id 、服务类型 code 查询应用与服务类型的绑定id
   * @param appId
   * @param platformChannelCode
   * @return
   */
  private Long selectIdByAppPlatformChannel(String appId,String platformChannelCode){
    AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>().eq(AppPlatformChannel::getAppId, appId)
            .eq(AppPlatformChannel::getPlatformChannel, platformChannelCode));
    if(appPlatformChannel!=null){
      return appPlatformChannel.getId();//应用与服务类型的绑定id
    }
    return null;
  }



}